﻿/*
 * @Author: wss 
 * @Date: 2019-08-21 17:45:35 
 * @Last Modified by: ws.s
 * @Last Modified time: 2021-10-14 09:32:34
 */

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using System.Text.RegularExpressions;


[RequireComponent(typeof(Text))]
[AddComponentMenu("UI/Behavior/RollNumber")]
public class UIRollNumber : MonoBehaviour
{
    public enum VALUE_TYPE
    {
        INTEGER,
        FIXED_2,
        TIMER,
        TIMER_FULL,
        PERCENTAGE,
        KMBT_FIXED2,
        THOUSAND_SEPARATOR,
        FIXED_1,
        CUSTOMER
    }

    const string REPLACE_STRING = "{{0}}";

    public Text textLabel;
    private float value;
    public bool showPlusSymbol = false;

    [SerializeField]
    private float _targetValue;
    [SerializeField]
    public float targetValue
    {
        get
        {
            return _targetValue;
        }
        set
        {
            _targetValue = value;
            Scroll();
        }
    }

    [Range(0, 0.5f), Tooltip("Lerp取值，越小越慢")]
    public float lerpValue = 0.1f;

    public bool playAtStart = true;

    [Range(0, 1.0f), Tooltip("滚动之前会等待几秒钟")]
    public float runWaitTimer = 0;

    public string formatTemplate = REPLACE_STRING;

    public VALUE_TYPE valueType = VALUE_TYPE.INTEGER;

    private bool isScrolling = false;
    private bool isDelayWait = false;

    [Tooltip("滚动开始时的事件")]
    public UnityEvent scrollStartEvent = null;

    [Tooltip("滚动停止时的事件")]
    public UnityEvent scrollEndEvent = null;

#if UNITY_EDITOR
    private void OnValidate()
    {
        Scroll();
    }
#endif

    private void Awake()
    {
        if (textLabel == null)
        {
            textLabel = GetComponent<Text>();
        }
        if (playAtStart)
        {
            UpdateText();
            Scroll();
        }
    }

    static string ParseTimer(float timer = 0, bool isFullTimer = true)
    {
        var t = timer;
        var hours = Mathf.FloorToInt(t / 3600);
        var mins = Mathf.FloorToInt((t % 3600) / 60);
        var secs = Mathf.FloorToInt(t % 60);
        string m = "" + mins;
        string s = "" + secs;
        if (secs < 10) s = "0" + secs;

        //full timer 按小时算,无论有没有小时
        if (isFullTimer)
        {
            if (mins < 10) m = "0" + mins;
            return hours + ':' + m + ':' + s;
        }
        else
        {
            m = "" + (mins + hours * 60);
            if (mins < 10) m = "0" + mins;
            return m + ':' + s;
        }
    }

    static Regex _regex_KMBT_FIXED2 = new Regex("E.*0");

    static string Format(float value, VALUE_TYPE type)
    {
        string str = "";
        switch (type)
        {
            case VALUE_TYPE.INTEGER://最终显示整数类型
                str = Mathf.Round(value) + "";
                break;
            case VALUE_TYPE.FIXED_2://最终显示两位小数类型
                str = value.ToString("F2");
                break;
            case VALUE_TYPE.FIXED_1://最终显示1位小数类型
                str = value.ToString("F1");
                break;
            case VALUE_TYPE.TIMER: //最终显示 计时器类型
                str = ParseTimer(value, false);
                break;
            case VALUE_TYPE.TIMER_FULL: //最终显示 计时器类型
                str = ParseTimer(value, true);
                break;
            case VALUE_TYPE.PERCENTAGE: //最终显示 百分比
                str = Mathf.Round(value * 100).ToString() + '%';
                break;
            case VALUE_TYPE.KMBT_FIXED2: //长单位缩放,只计算到 KMBT
                if (value >= float.MaxValue)
                {
                    str = "MAX";
                }
                else if (value >= 1000000000000000)
                {
                    str = _regex_KMBT_FIXED2.Replace((value).ToString("E1"), "E");
                }
                else if (value >= 1000000000000)
                {
                    str = (value / 1000000000000).ToString("F1") + 'T';
                }
                else if (value >= 1000000000)
                {
                    str = (value / 1000000000).ToString("F1") + 'B';
                }
                else if (value >= 1000000)
                {
                    str = (value / 1000000).ToString("F1") + 'M';
                }
                else if (value >= 9999)
                {
                    str = (value / 1000).ToString("F1") + "K";
                }
                else
                {
                    str = Mathf.RoundToInt(value).ToString();
                }
                break;
            case VALUE_TYPE.THOUSAND_SEPARATOR:
                str = Mathf.RoundToInt(value).ToString("N0");
                break;
            default:
                break;
        }

        //显示正负符号
        return str;
    }

    public void Scroll()
    {
        if (this.isScrolling) return;
        if (this.runWaitTimer > 0)
        {
            if (!this.isDelayWait)
            {
                isDelayWait = true;
                Invoke("ActiveScroll", runWaitTimer);
            }
        }
        else
        {
            ActiveScroll();
        }
    }

    public void ScrollTo(float target)
    {
        targetValue = target;
    }

    
    public void ForceSetValue(float value)
    {
        this.Stop();
        this.value = value;
        this.targetValue = value;
        UpdateText();
    }

    public void Stop()
    {
        value = targetValue;
        CancelInvoke("ActiveScroll");
        isDelayWait = false;
        isScrolling = false;
        UpdateText();
    }

    private void ActiveScroll()
    {
        isDelayWait = false;
        isScrolling = true;
    }

    private void UpdateText()
    {
        var value = this.value;
        var str = UIRollNumber.Format(value, this.valueType);

        //替换模板字符串 {{0}}
        if (this.formatTemplate.IndexOf(REPLACE_STRING) >= 0)
        {
            str = this.formatTemplate.Replace(REPLACE_STRING, str);
        }

        //显示正负符号
        if (this.showPlusSymbol)
        {
            if (value >= 0)
            {
                str = '+' + str;
            }
        }

        if (this.textLabel && this.valueType != VALUE_TYPE.CUSTOMER)
        {
            if (str == this.textLabel.text) return; //保证效率,如果上次赋值过,就不重复赋值
            this.textLabel.text = str;
        }
    }


    // Update is called once per frame
    void Update()
    {
        var dt = Time.deltaTime;
        if (isScrolling == false) return;
        var scale = (dt * 60);
        this.value = Mathf.Lerp(value, _targetValue, lerpValue * scale);

        UpdateText();

        if (Mathf.Abs(this.value - this._targetValue) <= 0.001f)
        {
            this.value = this._targetValue;
            scrollEndEvent.Invoke();
            isScrolling = false;
            return;
        }
    }
    
}
